# -*- coding: utf-8 -*-
import os
import sys
import logging
import hashlib
import time
import werkzeug.utils
from contextlib import closing
import jinja2
import openerp
from openerp import SUPERUSER_ID
from openerp import http
from openerp.http import request
from openerp.addons.auth_signup.controllers.main import AuthSignupHome as Home
from openerp.modules.registry import RegistryManager
from openerp.addons.web.controllers.main import login_redirect, db_monodb, ensure_db, set_cookie_and_redirect, login_and_redirect
from reportlab.graphics.barcode import createBarcodeDrawing
from openerp.addons.dftg_weixin.application.application_assistant import WxAppCropAssistant

_logger = logging.getLogger(__name__)

if hasattr(sys, 'frozen'):
    # When running on compiled windows binary, we don't have access to package loader.
    path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'html'))
    loader = jinja2.FileSystemLoader(path)
else:
    loader = jinja2.PackageLoader('openerp.addons.dftg_weixin', "html")
env = jinja2.Environment('<%', '%>', '${', '}', '%', loader=loader, autoescape=True)

#----------------------------------------------------------
# 重载odoo登录 Controller
#----------------------------------------------------------


class WeixinLogin(Home):

    @http.route()
    def web_login(self, *args, **kw):
        ensure_db()
        if request.httprequest.method == 'GET' and request.session.uid and request.params.get('redirect'):
            # Redirect if already logged in and redirect param is present
            return http.redirect_with_hash(request.params.get('redirect'))
        # 取得客户端ip
        remote_addr = request.httprequest.remote_addr
        if 'HTTP_X_REAL_IP' in request.httprequest.environ:
            remote_addr = request.httprequest.environ.get('HTTP_X_REAL_IP')
        request.params.setdefault('remote_addr', remote_addr)
        # 取得session md5
        session_md5 = hashlib.md5()
        session_md5.update(request.session_id)
        request.params.setdefault('session_md5', session_md5.hexdigest())
        temp_password = "%06d" % (abs(hash(session_md5.hexdigest())) % (10 ** 6))
        request.params.setdefault('temp_password', temp_password)

        response = super(WeixinLogin, self).web_login(*args, **kw)
        return response


#----------------------------------------------------------
# 微信统一身份认证登录 Controller
#----------------------------------------------------------

class WeixinLoginController(http.Controller):
    weixin_app = None

    def __init__(self):
        self.weixin_app = WxAppCropAssistant()

    #####################################################################
    #
    # 查是否微信登录
    #
    #####################################################################
    @http.route('/weixin/check_weixin_session', auth='public')
    def check_weixin_session(self, **kw):
        registry, cr, uid, context = request.registry, request.cr, request.session.uid, request.context
        weixin_session = registry.get('weixin.session')
        session_md5 = hashlib.md5()
        session_md5.update(request.session_id)
        session_ids = weixin_session.search(cr, SUPERUSER_ID, [('session_id', '=', session_md5.hexdigest()), ('check_time', '=', None)])
        result = 'ERROR'
        remote_addr = request.httprequest.remote_addr
        if 'HTTP_X_REAL_IP' in request.httprequest.environ:
            remote_addr = request.httprequest.environ.get('HTTP_X_REAL_IP')
        if session_ids:
            session_row = weixin_session.browse(cr, SUPERUSER_ID, session_ids[0])
            if session_row.user_id:
                res_users = registry.get('res.users')
                user_ids = res_users.search(cr, SUPERUSER_ID, [('id', '=', session_row.user_id)])

                if user_ids:
                    user_row = res_users.browse(cr, user_ids[0], user_ids[0])
                    if remote_addr != '112.64.141.214' and remote_addr != '127.0.0.1' and remote_addr != '192.168.0.45':
                        if not res_users.has_group(cr, user_ids[0], 'dftg_ext.outer_access')\
                                and not res_users.has_group(cr, user_ids[0], 'stock.group_stock_user')\
                                and not res_users.has_group(cr, user_ids[0], 'dftg_ext.outer_access'):
                            return '您没有权限从外部登录ERP系统，请联系系统管理员!'
                    uid = request.session.authenticate(request.session.db, user_row.login, user_row.oauth_access_token)
                    if uid:
                        session_row.write({'check_time': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())),
                                           'username': user_row.login,
                                           'ip': remote_addr})
                        cr.commit()
                        result = "OK"
                    else:
                        result = u"用户无法验证，可能没有同步到微信"
                else:
                    result = u'找不到用户%s，请联系系统管理员!session_row.user_id=' % (session_row.user_id)
            else:
                result = u'请关闭浏览器重新打开或者刷新页面再试一次'
        else:
            result = u'请关闭浏览器重新打开或者刷新页面再试一次'
        return result

    #####################################################################
    #
    # 通过微信登录odoo确认页面
    # * 此页面在微信浏览器中
    #
    #####################################################################
    @http.route('/weixin/login/<string:sid>', auth='weixin')
    def weixin_login_confirm(self, **kw):
        db_name = request.session.db
        sid = kw.get('sid')
        oauth_uid = request.session.oauth_uid
        user_id = request.session.uid
        # if not oauth_uid and not 'agentid' in kw:
        #     url = self.weixin_app.oauth_authorize_redirect_url(db_name, request.httprequest.host + '/weixin/login',
        #                                                        {'sid': sid})
        #     return werkzeug.utils.redirect(url)
        title = ''
        # 如果微信中已经登录过，则提示登录成功
        if oauth_uid:
            db = RegistryManager.get(db_name)
            title = u'扫码登录失败，请先进行账号绑定。'
            with closing(db.cursor()) as cr:
                res_user = db.get('res.users')
                user_ids = res_user.search(cr, 1, [('oauth_uid', '=', oauth_uid)])
                if user_ids:
                    # 可能微信浏览器session失效，需要重新取得user_id
                    user_id = user_ids[0]
                    db_user = res_user.browse(cr, SUPERUSER_ID, user_id)
                    weixin_session = openerp.registry(db_name)['weixin.session']
                    session_ids = weixin_session.search(cr, SUPERUSER_ID, [('session_id', '=', sid)])
                    if session_ids:
                        session_row = weixin_session.browse(cr, SUPERUSER_ID, session_ids[0])
                        session_row.write({'username': db_user.login, 'oauth_access_token': db_user.oauth_access_token,
                                           'user_id': user_id, 'oauth_uid': oauth_uid, 'check_time': None})
                        cr.commit()
                        # user_obj = db.get('res.users')
                        # user_ids = user_obj.search(cr, SUPERUSER_ID, [('oauth_uid', '=', req.FromUserName)])
                        title = u'用户' + db_user.login + u'扫码登录成功'
                        # user_id = user_ids[0]
                        # user = user_obj.browse(cr, 1, user_id)
                        db.get('bus.bus').sendone(cr, user_id, 'weixin_login', {'sid': sid})

                    else:
                        title = u'扫码登录失败，用户session不存在。'
                else:
                    title = u'扫码登录失败，用户不存在。'
        else:
            title = u'扫码登录失败，请在微信中扫码'

        template = env.get_template("weixin_login.html")
        return template.render({
            'user_id': user_id,
            'title': title
        })

    #####################################################################
    #
    # 生成session md5 二维码
    #
    #####################################################################
    @http.route('/weixin/weixin_login_qrcode', auth='public')
    def weixin_login_qrcode(self, type, value, width=600, height=100):
        """Contoller able to render barcode images thanks to reportlab.
        Samples:
            <img t-att-src="'/report/barcode/QR/%s' % o.name"/>
            <img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' %
                ('QR', o.name, 200, 200)"/>

        :param type: Accepted types: 'Codabar', 'Code11', 'Code128', 'EAN13', 'EAN8', 'Extended39',
        'Extended93', 'FIM', 'I2of5', 'MSI', 'POSTNET', 'QR', 'Standard39', 'Standard93',
        'UPCA', 'USPS_4State'
        """
        # qr = qrcode.QRCode(
        #     version = 1,
        #     error_correction = qrcode.constants.ERROR_CORRECT_L,
        #     box_size = 10,
        #     border = 4,
        # )
        # qr.add_data('Some data')
        # qr.make(fit=True)
        #
        #
        # img = qr.make_image()
        db_name = request.session.db
        # db = openerp.registry(db_name)

        session_md5 = hashlib.md5()
        session_md5.update(request.session_id)
        if value != session_md5.hexdigest():
            return 'error'

        # 商城用户检查
        registry = RegistryManager.get(db_name)
        with closing(registry.cursor()) as cr:
            weixin_session = registry.get('weixin.session')
            temp_password = "%06d" % (abs(hash(value)) % (10 ** 6))  # int(hashlib.sha1(value).hexdigest(), 16) % (10 ** 6)
            session_ids = weixin_session.search(cr, SUPERUSER_ID, [('temp_password', '=', temp_password)])
            #如果session_id hash后有重复的hash值，则进行删除后再新增
            if session_ids:
                    weixin_session.unlink(cr, SUPERUSER_ID, session_ids)
            #if not weixin_session.search(cr, SUPERUSER_ID, [('session_id', '=', value)]):
            values = {
                'session_id': value,
                'temp_password': temp_password,
            }
            weixin_session.create(cr, SUPERUSER_ID, values)
            cr.commit()

        try:
            width, height = int(width), int(height)
            if width > 600:
                width = 600
            if height > 600:
                height = 600
            url = "http://" + request.httprequest.host + "/weixin/login/" + value
            barcode = createBarcodeDrawing(
                type, value=url, format='png', width=width, height=height
            )
            barcode = barcode.asString('png')
        except (ValueError, AttributeError):
            raise openerp.exceptions.HTTPException(description='Cannot convert into barcode.')

        return request.make_response(barcode, headers=[('Content-Type', 'image/png')])

        # return img
